//==========================================================================
// Copyright (c) 2000-2009,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#ifndef __CGRAFIXOBJECT_H__
#define __CGRAFIXOBJECT_H__

#include <engine.h>

#define _NO_CGRAFIXOBJECT_CLASSOBJECT_
#include "_CGrafixObject.h"

#ifdef _DEBUG
#define     GRAFIXOBJECT_SIGN         0x87654321
#endif

typedef struct tagGrafixObjectConfig {
    // position and size
    //
    Rectangle bounds;

    Rectangle activeArea;

    // opacity factor
    //
    UInt8 opacity;

    Int32 priority;

    // flags for appearance/behaviour
    //
    GrafixAttribute option;

    // rectangles in the window transparent
    // baseplane to displayer overlayer.
    //
    Boolean layerTransparentEnable;
    RectangleLink transparentRect;
} GrafixObjectConfig;

typedef enum {
    GrafixObjectType_Common = 0x00000000,
    GrafixObjectType_Main = 0x00000001,
} GrafixObjectType;

typedef struct tagTimeData {
    Int32 id;
    Int32 waitTime;
    Int32 time;
} TimeData;

typedef enum {
    AnimationQualification_None = 0x00000000,
    AnimationQualification_Show = 0x00000001,
    AnimationQualification_Hide = 0x00000002,
} AnimationQualification;

typedef enum {
    AnimationFeasibility_None = 0x00000000,
    AnimationFeasibility_Show = 0x00000001,
    AnimationFeasibility_Hide = 0x00000002,
} AnimationFeasibility;

typedef enum {
    GrafixObjectVisibleSwitch_None = 0x00000000,
    GrafixObjectVisibleSwitch_Exposed = 0x00000001,
    GrafixObjectVisibleSwitch_CoveredUp = 0x00000002,
} GrafixObjectVisibleSwitch;

typedef enum {
    PaintStatus_None = 0x00000000,
    PaintStatus_Begin = 0x00000001,
    PaintStatus_Completed = 0x00000002,
    PaintStatus_NotNeed = 0x00000004,
} PaintStatus;

#define TIMER_COUNT 9 // count of timer

class CGrafixLayer;
class CGrafixSurface;

CarClass(CGrafixObject)
{
public:
    CARAPI Initialize(
        /* [in] */ GrafixObjectStack * pStack,
        /* [in] */ CGrafixSurface * pSurface,
        /* [in] */ WString title,
        /* [in] */ GrafixObjectParams params);

    ~CGrafixObject();

    Void *operator new(size_t size, void * pv) { return pv; }

    Void *operator new(size_t size) { return malloc(size); }

    Void operator delete(void * pv) { free(pv); }

public:
    CARAPI GetId(
        /* [out] */ Int32 * pObjId);

    CARAPI GetTitle(
        /* [out] */ WStringBuf * pTitle);

    CARAPI Attach(
        /* [in] */ Int32 contextId);

    CARAPI Detach();

    CARAPI AddEvent(
        /* [in] */ const struct GrafixObjectEvent & event);

    CARAPI AddNotifyEvent(
        /* [in] */ const struct GrafixObjectEvent & event);

    CARAPI RollbackEvent(
        /* [in] */ const struct GrafixObjectEvent & event);

    CARAPI SetUserDefinedHandles(
        /* [in] */ Handle32 usreDefinedId,
        /* [in] */ Handle32 usreDefinedHandle);

    CARAPI GetUserDefinedHandles(
        /* [out] */ Handle32 * pUsreDefinedId,
        /* [out] */ Handle32 * pUsreDefinedhandle);

    CARAPI SetOwner(
        /* [in] */ IGrafixObject * pOwnerObj);

    CARAPI GetOwner(
        /* [out] */ IGrafixObject ** ppOwnerObj);

    CARAPI GetGrafixSurface(
        /* [out] */ IGrafixSurface ** ppGrafixSurface);

    CARAPI SetOpacity(
        /* [in] */ Int32 opacity);

    CARAPI GetOpacity(
        /* [out] */ Int32 * pOpacity);

    CARAPI EnableGrafixLayerTransparent();

    CARAPI DisableGrafixLayerTransparent();

    CARAPI AddGrafixLayerTransparentRect(
        /* [in] */ Int32 x,
        /* [in] */ Int32 y,
        /* [in] */ Int32 width,
        /* [in] */ Int32 height);

    CARAPI RemoveGrafixLayerTransparentRect(
        /* [in] */ Int32 x,
        /* [in] */ Int32 y,
        /* [in] */ Int32 width,
        /* [in] */ Int32 height);

    CARAPI RemoveAllGrafixLayerTransparentRects();

    CARAPI GrabKey(
        /* [in] */ Int32 keyValue,
        /* [in] */ InputMask modifier);

    CARAPI UngrabKey(
        /* [in] */ Int32 keyValue,
        /* [in] */ InputMask modifier);

    CARAPI GrabPointer();

    CARAPI UngrabPointer();

    CARAPI SetPriority(
        /* [in] */ Int32 priority);

    CARAPI GetPriority(
        /* [out] */ Int32 * pPriority);

    CARAPI Move(
        /* [in] */ Int32 deltaX,
        /* [in] */ Int32 deltaY);

    CARAPI MoveTo(
        /* [in] */ Int32 x,
        /* [in] */ Int32 y);

    CARAPI Resize(
        /* [in] */ Int32 width,
        /* [in] */ Int32 height);

    CARAPI RaiseToTop();

    CARAPI LowerToBottom();

    CARAPI RequestFocus();

    CARAPI SetTimer(
        /* [in] */ Int32 timerId,
        /* [in] */ Int32 interval);

    CARAPI KillTimer(
        /* [in] */ Int32 timerId);

    CARAPI Close();

    CARAPI SetProperty(
        /* [in] */ GrafixObjectProperty property);

    CARAPI GetProperty(
        /* [out] */ GrafixObjectProperty * pProperty);

    CARAPI SetVisible(
        /* [in] */ Boolean visible);

    CARAPI IsVisible(
        /* [out] */ Boolean * pVisible);

    CARAPI SetInputEnabled(
        /* [in] */ Boolean enabled);

    CARAPI IsInputEnabled(
        /* [out] */ Boolean * pEnabled);

    CARAPI GetBounds(
        /* [out] */ Int32 * pX,
        /* [out] */ Int32 * pY,
        /* [out] */ Int32 * pWidth,
        /* [out] */ Int32 * pHeight);

    CARAPI SetBounds(
        /* [in] */ Int32 x,
        /* [in] */ Int32 y,
        /* [in] */ Int32 width,
        /* [in] */ Int32 height,
        /* [in] */ GrafixBound bound);

    CARAPI SetActiveArea(
        /* [in] */ const struct Rectangle & area);

    CARAPI InterceptKey(
        /* [in] */ Int32 keyValue,
        /* [in] */ InputMask modifier);

    CARAPI UninterceptKey(
        /* [in] */ Int32 keyValue,
        /* [in] */ InputMask modifier);

    CARAPI SetLeadingTransition(
        /* [in] */ TransitionEffect effect,
        /* [in] */ Int32 offsetX,
        /* [in] */ Int32 offsetY,
        /* [in] */ Int32 opacity,
        /* [in] */ Millisecond32 duration);

    CARAPI SetTrailingTransition(
        /* [in] */ TransitionEffect effect,
        /* [in] */ Int32 offsetX,
        /* [in] */ Int32 offsetY,
        /* [in] */ Int32 opacity,
        /* [in] */ Millisecond32 duration);

    CARAPI GetLeadingTransition(
        /* [out] */ TransitionEffect * peffect,
        /* [out] */ Int32 * pOffsetX,
        /* [out] */ Int32 * pOffsetY,
        /* [out] */ Int32 * pOpacity,
        /* [out] */ Millisecond32 * pDuration);

    CARAPI GetTrailingTransition(
        /* [out] */ TransitionEffect * peffect,
        /* [out] */ Int32 * pOffsetX,
        /* [out] */ Int32 * pOffsetY,
        /* [out] */ Int32 * pOpacity,
        /* [out] */ Millisecond32 * pDuration);

    CARAPI __Impl_SetObject(
        /* [in] */ IInterface * pObject);

    CARAPI __Impl_GetObject(
        /* [out] */ IInterface ** ppObject);

public:
    CARAPI CloseWithoutUpdate();

    Boolean Visible()
    {
        return (m_visible && m_config.opacity);
    }

    Boolean Transparent()
    {
        return Visible()
            && ((m_config.option & GrafixAttribute_AlphaPixel)
                || ((m_config.option & GrafixAttribute_AlphaChannel)
                    && m_config.opacity > 0 && m_config.opacity < 0xff));
    }

    Boolean LayerTransparent() {
        if (m_config.layerTransparentEnable
                && !m_config.transparentRect.IsEmpty()) {
            RectangleLink* node =
                (RectangleLink *)m_config.transparentRect.Next();
            while (node != &m_config.transparentRect) {
                if (!node->m_free) {
                    return TRUE;
                }

                node = (RectangleLink *)node->Next();
            }
        }

        return FALSE;
    }

    UInt32 GetPriority()
    {
        if (m_ownerGrafixObject) {
            return (m_ownerGrafixObject->GetPriority() + m_config.priority);
        }
        else {
            return m_config.priority;
        }
    }

    Boolean IsOwner(
        /* [in] */ CGrafixObject * pGrafixObject)
    {
        CGrafixObject* owner = pGrafixObject->m_ownerGrafixObject;

        while (owner) {
            if (this == owner) {
                return TRUE;
            }

            owner = owner->m_ownerGrafixObject;
        }

        return FALSE;
    }

    Void  CleanEventBuffer();

    CARAPI Update(
        /* [in] */ Region * pUpdateRegion = NULL);

    CARAPI Draw(
        /* [in] */ CGrafixSurface * pDestination,
        /* [in] */ Region * region);

    CARAPI SetTimeEvent(
        /* [in] */ Int32 currentTime);

    CARAPI NotifyEventBuffer(
        /* [in] */ NotifyType type);

    CARAPI SetBounds(
        /* [in] */ Rectangle * pRect);

public:
    wchar_t* m_title;
    Int32 m_objId;

    Handle32 m_userDefinedId;
    IInterface* m_userObject;
    Handle32 m_userDefinedHandle;

    GrafixObjectType m_type;     // app main window

    Boolean m_visible;

    GrafixObjectConfig m_config;

    CGrafixSurface* m_surface;  // backing store surface
    Boolean m_bufferChanged;

    GrafixObjectStack* m_stack;    // window stack the window belongs

    Boolean m_haveTimeEvent;
    TimeData m_timeData[TIMER_COUNT];
    UInt32 m_timeEvent[TIMER_COUNT];

    CGrafixEventBuffer* m_eventBuffer;

    CGrafixObject* m_ownerGrafixObject;

    Int32 m_appletId;
    Int32 m_contextId;

    GrafixObjectProperty m_status;

    Boolean m_enableInput;

    Boolean m_alive;
    Boolean m_sendClosedMessage;

    Boolean m_needPaint;
    PaintStatus m_paintStatus;

    GrafixObjectVisibleSwitch m_visibleSwitch;
    Boolean m_exposed;

    Int32 m_animationFeasibility;   // the state shows that window is changed
                                    // from invisible to visible --- AnimationFeasibility_Show,
                                    // or from visible to invisible --- AnimationFeasibility_Hide.

    Int32 m_animationQualification; // the state shows that user calls methods
                                    // (e.g. SetVisible, RaiseToTop, SetOpacity, etc.)
                                    // to show window --- AnimationQualification_Show
                                    // or to hide window --- AnimationQualification_Hide

    // when Both m_leadingEffect and m_trailingEffect is TRUE, the window
    // animation be show.
    //
    TransitionEffect m_leadingEffect;
    TransitionEffect m_trailingEffect;

#ifdef _DEBUG
    UInt32 m_sign;
#endif
    Boolean m_render;   // whether cache buffer is released when window is
                        // covered up.
                        // it is set TRUE in GetFlip method, and set False
                        // in RenderDriver in grafixobjectstack.cpp.
                        // because buffer can be got by method, it can't
                        // judge validity by reference.

    Boolean m_animationSymbol;
    Boolean m_showing;

    Boolean m_orientationChanged;

    Int32 m_leadingOffsetX;
    Int32 m_leadingOffsetY;
    Int32 m_leadingOpacity;
    Int32 m_leadingDuration;

    Int32 m_trailingOffsetX;
    Int32 m_trailingOffsetY;
    Int32 m_trailingOpacity;
    Int32 m_trailingDuration;
};

#endif // __CGRAFIXOBJECT_H__
